// $Id: text_decoding.c 29 2015-03-11 03:49:12Z robim.poa@gmail.com $
//-----------------------------------------------------------------------------
// Purpose: Text reading and decoding.
// $Rev: 29 $
// $Author: robim.poa@gmail.com $
// $Date: 2015-03-11 03:49:12 +0000 (Wed, 11 Mar 2015) $

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "debug.h"
#include "text_decoding.h"

char tdGetNonBlankChar(FILE *pfile)
{
	char nonblankchar = ' ';
	while((nonblankchar == ' ') || (nonblankchar == '\t') || (nonblankchar == '\n') || (nonblankchar == '\r'))
	{
		nonblankchar = tdGetChar(pfile);
	}
	return nonblankchar;
}

void tdGetString(char *str, FILE *pfile)
{
	char   character = ' ';
	int    i = 0;
	fpos_t pos;

	character = tdGetNonBlankChar(pfile);

	while(
		(character!=';') && (character!='=') && (character!='|') && (character!='&') && (character!='!')  && (character!='<')  && (character!='>') && (character!=',')  &&
		(character!='+') && (character!='-') && (character!='/') && (character!='*') && (character!='%')  && (character!='^')  && (character!='(') && (character!=')')  &&
		(character!='[') && (character!=']') && (character!='{') && (character!='}') && (character!='\n') && (character!='\t') && (character!=' ') && (character!='\r') && (character!=EOF))
	{
		fgetpos(pfile,&pos);
		str[i] = character;
		i++;
		character = tdGetChar(pfile);
	}
	str[i] = '\0';
	fsetpos(pfile, &pos);
}

int tdGetOperator(char *str, FILE *pfile)
{
	char   character;
	int    i = 0;
	fpos_t pos;
	
	character = tdGetNonBlankChar(pfile);
	fgetpos(pfile,&pos);

	if(
		character == '(' || character == ')' || character == '[' || character == ']' || character == '{' || character == '}' || character == ',' ||
		character == ';' || character == '*' || character == '^')
	{
		str[i] = character;
		i++;
	}
	else
		while(
			(character=='=') || (character=='|') || (character=='&') || (character=='!') || (character=='<') || (character=='>') ||
			(character=='+') || (character=='-') || (character=='/') || (character=='%'))
		{
			fgetpos(pfile,&pos);
			str[i] = character;
			i++;
			character = tdGetChar(pfile);
		}

	str[i] = '\0';
	fsetpos(pfile,&pos);
	
	return tdStringToOperator(str);
}

int tdStringToOperator(char* buffer)
{
	int operator;

	if(!strcmp(buffer, "="))
	{
		operator = ARITHMETIC_OPERATOR_EQUAL;
	}
	else if(!strcmp(buffer, "+"))
	{
		operator = ARITHMETIC_OPERATOR_PLUS;
	}
	else if(!strcmp(buffer, "-"))
	{
		operator = ARITHMETIC_OPERATOR_MINUS;
	}
	else if(!strcmp(buffer, "*"))
	{
		operator = ARITHMETIC_OPERATOR_MULTI;
	}
	else if(!strcmp(buffer, "/"))
	{
		operator = ARITHMETIC_OPERATOR_DIVIS;
	}
	else if(!strcmp(buffer, "%"))
	{
		operator = ARITHMETIC_OPERATOR_MODULO;
	}
	else if(!strcmp(buffer, "^"))
	{
		operator = ARITHMETIC_OPERATOR_POWER;
	}
	else if(!strcmp(buffer, "=="))
	{
		operator = COMPARISON_OPERATOR_EQUAL;
	}
	else if(!strcmp(buffer, "!="))
	{
		operator = COMPARISON_OPERATOR_NEQUAL;
	}
	else if(!strcmp(buffer, "||"))
	{
		operator = LOGIC_OPERATOR_OR;
	}
	else if(!strcmp(buffer, "&&"))
	{
		operator = LOGIC_OPERATOR_AND;
	}
	else if(!strcmp(buffer, "!"))
	{
		operator = LOGIC_OPERATOR_NOT;
	}
	else if(!strcmp(buffer, ">"))
	{
		operator= COMPARISON_OPERATOR_GREATER;
	}
	else if(!strcmp(buffer, "<"))
	{
		operator = COMPARISON_OPERATOR_LESS;
	}
	else if(!strcmp(buffer, ">="))
	{
		operator = COMPARISON_OPERATOR_GREATER_EQUAL;
	}
	else if(!strcmp(buffer, "<="))
	{
		operator = COMPARISON_OPERATOR_LESS_EQUAL;
	}
	else if(!strcmp(buffer, "("))
	{
		operator = BRACKETS_PARENTHESES_OPEN;
	}
	else if(!strcmp(buffer, ")"))
	{
		operator = BRACKETS_PARENTHESES_CLOSE;
	}
	else if(!strcmp(buffer, "{"))
	{
		operator = BRACKETS_BRACES_OPEN;
	}
	else if(!strcmp(buffer, "}"))
	{
		operator = BRACKETS_BRACES_CLOSE;
	}
	else if(!strcmp(buffer, "["))
	{
		operator = BRACKETS_SQUARE_OPEN;
	}
	else if(!strcmp(buffer, "]"))
	{
		operator = BRACKETS_SQUARE_CLOSE;
	}
	else if(!strcmp(buffer, ";"))
	{
		operator = SYNTAX_MARK_SEMICOLON;
	}
	else
	{
		printf("Critical error: tdStringToOperator\n");
		operator = OPERATOR_NONE;
	}

	#ifdef DEBUG
		printf("Operator: %s\n", buffer);
	#endif

	return operator;
}

int tdIsNumber(char* str)
{
	int i;

	for(i=0; str[i]!='\0'; i++)
	{
		if(str[i]<48 || str[i]>57)
			return 0;
	}
	return 1;
}

int tdStrToInt(char *str)
{
	int i, length, value = 0;

	for(length=0; str[length]!='\0'; length++);
	
	for(i = length; i>0; i--)
	{
		value += (str[i-1]-48)*pow(10, length-i);
	}
	return value;
}

char tdLookNextChar(FILE* pfile)
{
	char   character;
	fpos_t pos;
	
	fgetpos(pfile, &pos);
	character = tdGetNonBlankChar(pfile);
	fsetpos(pfile, &pos);

	return character;
}

char tdGetChar(FILE* pfile)
{
	char character = fgetc(pfile);

	if(character == EOF)
	{
		printf("%d:error: unexpected end of file", tdGetLine(pfile));
		exit(EXIT_FAILURE);
	}

	return character;
}

void tdLookNextString(char *str, FILE *pfile)
{
	char   character = ' ';
	int    i = 0;
	fpos_t pos;

	fgetpos(pfile,&pos);

	character = tdGetNonBlankChar(pfile);

	while(
		(character!=';') && (character!='=') && (character!='|') && (character!='&') && (character!='!')  && (character!='<')  && (character!='>') && (character!=',') &&
		(character!='+') && (character!='-') && (character!='/') && (character!='*') && (character!='%')  && (character!='^')  && (character!='(') && (character!=')') &&
		(character!='[') && (character!=']') && (character!='{') && (character!='}') && (character!='\n') && (character!='\t') && (character!=' ') && (character!='\r'))
	{
		str[i] = character;
		i++;
		character = tdGetChar(pfile);
	}
	str[i] = '\0';
	fsetpos(pfile, &pos);
}

int tpStringToStatement(char* buffer)
{
	int statement;

	if(!strcmp(buffer, "while"))
	{
		printf("Statement: while\n");
		statement = STATEMENT_WHILE;
	}

	else if(!strcmp(buffer, "for"))
	{
		printf("Statement: for\n");
		statement = STATEMENT_FOR;
	}

	else if(!strcmp(buffer, "if"))
	{
		printf("Statement: if\n");
		statement = STATEMENT_IF;
	}

	else if(!strcmp(buffer, "else"))
	{
		printf("Statement: else\n");
		statement = STATEMENT_ELSE;
	}

	else if(!strcmp(buffer, "switch"))
	{
		printf("Statement: switch\n");
		statement = STATEMENT_SWITCH;
	}

	else if(!strcmp(buffer, "int"))
	{
		statement = STATEMENT_TYPE_INT;
	}

	else if(!strcmp(buffer, "char"))
	{
		statement = STATEMENT_TYPE_CHAR;
	}

	else if(!strcmp(buffer, "double"))
	{
		statement = STATEMENT_TYPE_DOUBLE;
	}

	else if(!strcmp(buffer, "float"))
	{
		statement = STATEMENT_TYPE_FLOAT;
	}

	else
	{
		statement = STATEMENT_NONE;
	}

	return statement;
}

int tdGetLine(FILE *pfile)
{
	long int pos_init, pos;
	int      line = 1;

	pos_init = ftell(pfile);

	fseek(pfile, 0, SEEK_SET);

	pos = ftell(pfile);

	while(pos < pos_init)
	{
		if(tdGetChar(pfile) == '\n')
			line++;

		pos = ftell(pfile);
	}

	return line;
}

int tdEndOfFile(FILE *pfile)
{
	fpos_t pos;
	char   nonblankchar = ' ';
	
	fgetpos(pfile,&pos);

	while((nonblankchar == ' ') || (nonblankchar == '\t') || (nonblankchar == '\n') || (nonblankchar == '\r'))
	{
		nonblankchar = fgetc(pfile);
	}

	if(nonblankchar == EOF)
	{
		return 1;
	}
	else
	{
		fsetpos(pfile, &pos);
		return 0;
	}
}